package com.alks.function.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.handler.WorkbookWriteHandler;
import com.alibaba.excel.write.handler.context.WorkbookWriteHandlerContext;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.fastjson2.JSON;
import com.alks.common.aop.AutoPageAop;
import com.alks.common.data.thread.UserIdThread;
import com.alks.common.service.RedisService;
import com.alks.common.utils.DateUtils;
import com.alks.common.utils.beanutils.ObjectUtils;
import com.alks.common.utils.excelUtils.ExcelPoiUtils;
import com.alks.common.utils.excelUtils.ExcelUtils;
import com.alks.common.utils.stringUtils.ZStringUtils;
import com.alks.entity.data.entity.*;
import com.alks.entity.data.entity.excel.PcOrderPlanExcel;
import com.alks.entity.data.enums.ResultCodeEnum;
import com.alks.entity.data.response.ResponseInfo;
import com.alks.entity.exception.ServiceErrorException;
import com.alks.function.data.dto.PcProdDynamicDto;
import com.alks.function.data.request.prod.ProdDynamicDetailRequest;
import com.alks.function.data.request.prod.ProdDynamicRequest;
import com.alks.function.mapper.ProdDynamicHeadMapper;
import com.alks.function.service.PcProdDynamicService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author:xxxxx
 * @create: 2023-07-04 10:30
 * @Description: 生产动态
 */
@Service
@Slf4j
public class PcProdDynamicServiceImpl extends ServiceImpl<ProdDynamicHeadMapper, ProdDynamicHeadRep> implements PcProdDynamicService {
    @Value("${file.path}")
    private String path;
    @Autowired
    ProdDynamicHeadMapper prodDynamicHeadMapper;

    @Override
    public ResponseInfo listPcDynamicCondition() {
        ProdDynamicCondition prodDynamicCondition = new ProdDynamicCondition();
        List<String> brands = prodDynamicHeadMapper.getBrands();
        List<String> samples = prodDynamicHeadMapper.getSamples();
        List<String> purType = prodDynamicHeadMapper.getPurType();
        List<String> seasons = prodDynamicHeadMapper.getSeasons();
        List<Map<String, String>> vendors = prodDynamicHeadMapper.getVendors();
        List<String> sysUser = prodDynamicHeadMapper.getSysUser();
        List<String> styles = prodDynamicHeadMapper.getStyles();
        prodDynamicCondition.setBrands(brands);
        prodDynamicCondition.setSamples(samples);
        prodDynamicCondition.setPurType(purType);
        prodDynamicCondition.setSeasons(seasons);
        prodDynamicCondition.setStyles(styles);
        prodDynamicCondition.setVendors(vendors);
        prodDynamicCondition.setSysUser(sysUser);
        return ResponseInfo.ok(prodDynamicCondition);
    }

    @Autowired
    RedisService redisService;

    @Override
    public ResponseInfo getPcProdDynamicList(ProdDynamicRequest request) {
        String key = request.toString() + request.getPageSize() + request.getPageNum();
        Set scan = redisService.scan(key);
        if (!scan.isEmpty()) {
            String dto = redisService.get(key);
            PcProdDynamicDto pcProdDynamicDto = JSON.parseObject(dto, PcProdDynamicDto.class);
            return ResponseInfo.ok(pcProdDynamicDto);
        }
        if (request == null) {
            return ResponseInfo.error(ResultCodeEnum.LOGIN_CONFIG_IS_NULL.getMessage(), ResultCodeEnum.LOGIN_CONFIG_IS_NULL.getCode());
        }
        if (request.getPageNum() == null || request.getPageSize() == null) {
            request.setPageNum(1);
            request.setPageSize(10);
        }
        PageHelper.startPage(request.getPageNum(), request.getPageSize(), false);
        PcProdDynamicDto dto = new PcProdDynamicDto();
        List<ProdDynamicHeadRep> pcProdDynamicList = prodDynamicHeadMapper.getPcProdDynamicList(request);
        //设置采购状态
        List<String> purs = prodDynamicHeadMapper.getProdDynamicPurs();
        //设置入库状态
        List<String> ins = prodDynamicHeadMapper.getProdDynamicIns();
        List<ProdDynamicHeadRep> reps = pcProdDynamicList.stream().map(new Function<ProdDynamicHeadRep, ProdDynamicHeadRep>() {
            @Override
            public ProdDynamicHeadRep apply(ProdDynamicHeadRep prodDynamicHeadRep) {
                if (!purs.contains(prodDynamicHeadRep.getLotNo())) {
                    prodDynamicHeadRep.setPurStatus("OK");
                }
                if (!ins.contains(prodDynamicHeadRep.getLotNo())) {
                    prodDynamicHeadRep.setInStatus("OK");
                }
                return prodDynamicHeadRep;
            }
        }).collect(Collectors.toList());
        dto.setList(reps);
        Long total = prodDynamicHeadMapper.getPcProdDynamicTotal(request);
        dto.setTotal(total);
        BigDecimal qtyTotal = prodDynamicHeadMapper.getPcProdDynamicQtyTotal(request);
        dto.setQtyTotal(qtyTotal);
        redisService.set(key, JSON.toJSONString(dto));
        return ResponseInfo.ok(dto);
    }

    @Override
    public ResponseInfo getProdDynamicDetail(ProdDynamicDetailRequest request) {
        if (request == null) {
            return ResponseInfo.error(ResultCodeEnum.LOGIN_CONFIG_IS_NULL.getMessage(), ResultCodeEnum.LOGIN_CONFIG_IS_NULL.getCode());
        }
        if (request.getLotNo() == null || "".equals(request.getLotNo())) {
            return ResponseInfo.error(ResultCodeEnum.LOGIN_CONFIG_IS_NULL.getMessage(), ResultCodeEnum.LOGIN_CONFIG_IS_NULL.getCode());
        }
        List<PcProdDynamicDetail> list = prodDynamicHeadMapper.getProdDynamicDetail(request);
        return ResponseInfo.ok(list);
    }

    @Override
    @AutoPageAop
    public ResponseInfo getPreOrderList(PcProdPreReq req) {
        Map<String, Object> map = new HashMap<>();
        List<PcProdOrderRep> list = prodDynamicHeadMapper.getPreOrderList(req);
        BigDecimal preTotal = prodDynamicHeadMapper.getPreOrderPreQtys(req);
        Page<PcProdOrderRep> page = (Page<PcProdOrderRep>) list;
        map.put("map", list);
        map.put("total", page.getTotal());
        map.put("preTotal", preTotal);
        return ResponseInfo.ok(map);
    }

    @Override
    @Transactional
    public ResponseInfo updateRecoverLot(PcLotRecoverReq req) {
        //指令结束
        List<String> list = req.getList();
        switch (req.getChoose()) {
            case "1":
                prodDynamicHeadMapper.updateLotOver(list);
                return ResponseInfo.ok("指令已结束");
            case "2":
                for (String orderId : list) {
                    Integer count = prodDynamicHeadMapper.selectByLots(orderId);
                    if (count > 0) {
                        return ResponseInfo.error(orderId + "订单成型已完成，不能恢复");
                    }
                }
                prodDynamicHeadMapper.updateLotRecover(list);
                return ResponseInfo.ok("指令已恢复");
            case "3":
                //添加数据到 pc_schedule_lot 中
                Date date = new Date();
                String format = new SimpleDateFormat("yyyyMMdd").format(date);
                BigDecimal stkQty = new BigDecimal("0");
                List<PcScheduleRep1> lists = prodDynamicHeadMapper.getPcScheduleList2(format);
                BigDecimal orderQtys = prodDynamicHeadMapper.getOrderQty(list);
                for (PcScheduleRep1 x : lists) {
                    BigDecimal scheduleQty = x.getSchQty() == null ? new BigDecimal("0") : x.getSchQty();
                    stkQty = stkQty.add(scheduleQty);
                }
                stkQty = stkQty.add(orderQtys);
                LocalDate today = LocalDate.now();
                prodDynamicHeadMapper.insertIntoPcSchByHead(list);
                prodDynamicHeadMapper.updatePcSchLot(list);
                return ResponseInfo.ok("进度安排成功");
            case "4":
                //将数据从pc_schedule_lot 删除
                prodDynamicHeadMapper.deleteByLotNos(list);
                return ResponseInfo.ok("取消安排成功");
            default:
                return ResponseInfo.error("检查参数");
        }
    }

    @Override
    public ResponseInfo getPcScheduleList(String lotNo, String shoeName, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        Map<String, Object> map = new HashMap<>();
        List<PcScheduleRep1> list = prodDynamicHeadMapper.getPcScheduleList(lotNo, shoeName);
        Page<PcScheduleRep1> page = (Page<PcScheduleRep1>) list;
        BigDecimal schTotal = prodDynamicHeadMapper.getPcScheduleListSchTotal(lotNo, shoeName);
        BigDecimal prodDays = prodDynamicHeadMapper.getPcScheduleProdTotal(lotNo, shoeName);
        map.put("list", list);
        map.put("total", page.getTotal());
        map.put("schTotal", schTotal);
        map.put("prodDays", prodDays);
        return ResponseInfo.ok(map);
    }

    @Override
    @Transactional
    public ResponseInfo updateScheduleDetail() {
        Date date = new Date();
        String format = new SimpleDateFormat("yyyyMMdd").format(date);
        //查询进度表中是否含有当天的数据 如果有将生产天数以及完成日期客户交期重置
        Integer count = prodDynamicHeadMapper.getCurrentList(format);
        List<PcScheduleRep1> list = prodDynamicHeadMapper.getPcScheduleList2(format);
        List<String> orderIdList = prodDynamicHeadMapper.getOrderIdByProd(list);
        List<PcScheduleRep1> collect = list.stream().filter(x -> !orderIdList.contains(x.getLotNo())).collect(Collectors.toList());
        BigDecimal stkQty = new BigDecimal("0");
        for (PcScheduleRep1 x : list) {
            BigDecimal scheduleQty = x.getSchQty() == null ? new BigDecimal("0") : x.getSchQty();
            stkQty = stkQty.add(scheduleQty);
        }
        //本月多少天
        BigDecimal divide = new BigDecimal(prodDynamicHeadMapper.getStdQty(UserIdThread.get().getCompanyId()));
        if (count <= 0) {
            prodDynamicHeadMapper.insertIntoPcSch(collect, format, divide);
        }
        prodDynamicHeadMapper.setEmptyPcSch(format);
        return ResponseInfo.ok("成功");
    }

    @Override
    @Transactional
    public ResponseInfo computeProdDate(String order) {
        Integer stdQty = prodDynamicHeadMapper.getStdQty(UserIdThread.get().getCompanyId());
        List<PcScheduleRep1> list = prodDynamicHeadMapper.getPcScheduleList1(order);
        BigDecimal bigDecimal = new BigDecimal("0");
        LocalDate now = LocalDate.now();
        BigDecimal seq = new BigDecimal("0");
        for (PcScheduleRep1 pcScheduleRep1 : list) {
            pcScheduleRep1.setCompanyId(UserIdThread.get().getCompanyId());
            BigDecimal schQty = pcScheduleRep1.getSchQty();
            BigDecimal divide = schQty.divide(new BigDecimal(stdQty), 2, RoundingMode.HALF_UP);
            bigDecimal = bigDecimal.add(divide);
            if (bigDecimal.intValue() >= 1) {
                now = now.plusDays(1);
                bigDecimal = new BigDecimal("0");
            }
            pcScheduleRep1.setProdDays(divide);
            pcScheduleRep1.setStartDate(now.format(DateTimeFormatter.ISO_DATE));
            pcScheduleRep1.setEndDate(now.format(DateTimeFormatter.ISO_DATE));
            seq = seq.add(new BigDecimal(1));
            pcScheduleRep1.setSeqNo(seq);
        }
        prodDynamicHeadMapper.deleteSchNo();
        prodDynamicHeadMapper.insertIntoList(list);
        return ResponseInfo.ok("计算成功");
    }

    @Override
    @Transactional
    public ResponseInfo upDown(String upDown, List<PcScheduleRep1> req) {
        req.sort(Comparator.comparing(PcScheduleRep1::getSeqNo));
        PcScheduleRep1 rep1 = req.get(0);
        PcScheduleRep1 rep2 = req.get(req.size() - 1);
        BigDecimal seqNo = rep1.getSeqNo().subtract(new BigDecimal(1));
        BigDecimal seqNo1 = rep2.getSeqNo().add(new BigDecimal(1));
        String year = DateUtils.getYear(new Date());
        req.forEach(x->x.setStartDate(year+"/"+x.getStartDate()));
        switch (upDown) {
            case "1":
                //交换区号
                prodDynamicHeadMapper.deleteUp(req);
                req.forEach(x->x.setSeqNo(x.getSeqNo().subtract(new BigDecimal(1))));
                prodDynamicHeadMapper.updateSeq(rep1.getScheduleNo(), seqNo,req.size());
                prodDynamicHeadMapper.up(req);
                break;
            case "2":
                prodDynamicHeadMapper.deleteUp(req);
                req.forEach(x->x.setSeqNo(x.getSeqNo().add(new BigDecimal(1))));
                prodDynamicHeadMapper.updateSeq1(rep1.getScheduleNo(),seqNo1,req.size());
                prodDynamicHeadMapper.up(req);
                break;
        }
        return ResponseInfo.ok("移动成功");
    }

    @Override
    @Transactional
    public ResponseInfo batchMove(BatchMoveReq req) {
        List<PcScheduleRep1> list = prodDynamicHeadMapper.getPcSchList();
        List<PcScheduleRep1> cList = req.getList();
        List<String> cLots = cList.stream().map(PcScheduleRep1::getLotNo).collect(Collectors.toList());
        //指定位置
        int eNum = new BigDecimal(req.getSeqNo()).intValue();
        List<PcScheduleRep1> finalList = new ArrayList<>();

        //数据库数据里的list
        cList = list.stream().filter(x -> cLots.contains(x.getLotNo())).collect(Collectors.toList());

        List<PcScheduleRep1> newList = list.stream().filter(x -> {
            boolean bool = false;
            if (x.getSeqNo().intValue() < eNum && !cLots.contains(x.getLotNo())) {
                bool = true;
            }
            return bool;
        }).collect(Collectors.toList());
        List<String> newLots = newList.stream().map(PcScheduleRep1::getLotNo).collect(Collectors.toList());
        List<PcScheduleRep1> midList = list.stream().filter(x -> {
            boolean bool = true;
            if (cLots.contains(x.getLotNo()) || newLots.contains(x.getLotNo())) {
                bool = false;
            }
            return bool;
        }).collect(Collectors.toList());

        int countNum = 1;

        for (PcScheduleRep1 x : newList) {
            x.setSeqNo(BigDecimal.valueOf(countNum++));
            finalList.add(x);
        }

        int breakNum = 0;

        loop:
        for (PcScheduleRep1 re1 : list) {
            for (PcScheduleRep1 re2 : cList) {
                if (re1.getLotNo().equals(re2.getLotNo())) {
                    re2.setSeqNo(BigDecimal.valueOf(countNum++));
                    finalList.add(re2);
                    breakNum++;
                    if (breakNum == cList.size()) {
                        break loop;
                    }
                }
            }
        }
        for (PcScheduleRep1 x : midList) {
            x.setSeqNo(new BigDecimal(countNum++));
            finalList.add(x);
        }
        finalList.forEach(x -> x.setCompanyId(UserIdThread.get().getCompanyId()));
        prodDynamicHeadMapper.deleteSchNo();
        prodDynamicHeadMapper.insertByFinalList(finalList);
        return ResponseInfo.ok("移动成功");
    }

    @AutoPageAop
    @Override
    public ResponseInfo arrangePlanList(PcProdArrangeReq req) {
        Map<String, Object> map = new HashMap<>();
        String plan = null;
        List<MtlDPlanArrangeRep> list = null;
        Page<MtlDPlanArrangeRep> page = null;
        List<PcStitchPlanRep> sList = null;
        Page<PcStitchPlanRep> sPage = null;
        switch (req.getChoose()) {
            case "1":
                plan = "MTL";
                list = prodDynamicHeadMapper.arrangePlanList(plan, req);
                page = (Page<MtlDPlanArrangeRep>) list;
                map.put("list", list);
                map.put("total", page.getTotal());
                break;
            case "2":
                plan = "DESIGN";
                list = prodDynamicHeadMapper.arrangePlanList(plan, req);
                page = (Page<MtlDPlanArrangeRep>) list;
                map.put("list", list);
                map.put("total", page.getTotal());
                break;
            case "3":
                plan = "STITCH";
                sList = prodDynamicHeadMapper.arrangePlanListStitch(plan, req);
                sPage = (Page<PcStitchPlanRep>) sList;
                map.put("list", sList);
                map.put("total", sPage.getTotal());
                break;
            case "4":
                plan = "SOLE";
                list = prodDynamicHeadMapper.arrangePlanList(plan, req);
                page = (Page<MtlDPlanArrangeRep>) list;
                map.put("list", list);
                map.put("total", page.getTotal());
                break;
            case "5":
                plan = "LAST";
                list = prodDynamicHeadMapper.arrangePlanList(plan, req);
                page = (Page<MtlDPlanArrangeRep>) list;
                map.put("list", list);
                map.put("total", page.getTotal());
                break;
        }
        return ResponseInfo.ok(map);
    }

    @Override
    @AutoPageAop
    public ResponseInfo choosePlanList(PcProdArrangeReq req) {
        Map<String, Object> map = new HashMap<>();
        List<MtlDPlanArrangeRep> list = prodDynamicHeadMapper.choosePlanList(req);
        Page<MtlDPlanArrangeRep> page = (Page<MtlDPlanArrangeRep>) list;
        map.put("list", list);
        map.put("total", page.getTotal());
        return ResponseInfo.ok(map);
    }

    @Override
    public ResponseInfo chooseProdStatusIn(List<String> list, String choose) {
        prodDynamicHeadMapper.insertIntoPcPlan(list, choose);
        return ResponseInfo.ok("插入成功");
    }

    @Override
    public ResponseInfo updatePcOrderPlan(MtlDPlanArrangeRep req, String choose) {
        prodDynamicHeadMapper.updatePcOrderPlan(req, choose);
        return ResponseInfo.ok("修改成功");
    }

    @Override
    public ResponseInfo removePcOrderPlan(MtlDPlanArrangeRep req, String choose) {
        prodDynamicHeadMapper.removePcOrderPlan(req, choose);
        return ResponseInfo.ok("删除成功");
    }

    @Override
    public ResponseInfo cutProdStatusList(String date, String choose, Integer pageNum, Integer pageSize) {
        Map<String, Object> map = new HashMap<>();
        Date day = new Date();
        String format = new SimpleDateFormat("yyyyMM").format(day);
        List<PcCutProdStatusRep> clist = prodDynamicHeadMapper.cutProdStatusList(format, "2");
        if (!clist.isEmpty() && Integer.parseInt(choose) == 2) {
            return ResponseInfo.error("本月资料已存在");
        }
        PageHelper.startPage(pageNum, pageSize);
        List<PcCutProdStatusRep> list = prodDynamicHeadMapper.cutProdStatusList(date, choose);
        Page<PcCutProdStatusRep> page = (Page<PcCutProdStatusRep>) list;
        map.put("list", list);
        map.put("total", page.getTotal());
        return ResponseInfo.ok(map);
    }

    @Override
    public ResponseInfo updateProdStatus(PcCutProdStatusRep req, String choose) {
        Integer num = 0;
        req.setCompanyId(UserIdThread.get().getCompanyId());
        switch (choose) {
            case "1":
                num = prodDynamicHeadMapper.insertProdStatus(req);
                if (num <= 0) {
                    return ResponseInfo.error("插入失败");
                }
                return ResponseInfo.ok("插入成功");
            case "2":
                num = prodDynamicHeadMapper.deleteByProdStatus(req);
                if (num <= 0) {
                    return ResponseInfo.error("删除失败");
                }
                return ResponseInfo.ok("删除成功");
            case "3":
                num = prodDynamicHeadMapper.updateByProdStatus(req);
                if (num <= 0) {
                    return ResponseInfo.error("更新失败");
                }
                return ResponseInfo.ok("更新成功");
            default:
                return ResponseInfo.error("检查choose参数");
        }
    }

    @Override
    @AutoPageAop
    public ResponseInfo devPartDayPlanList(PcDevPartDayPlanReq req) {
        Map<String, Object> map = new HashMap<>();
        List<MtlDPlanArrangeRep> list = prodDynamicHeadMapper.devPartDayPlanList(req);
        Page<MtlDPlanArrangeRep> page = (Page<MtlDPlanArrangeRep>) list;
        map.put("list", list);
        map.put("total", page.getTotal());
        return ResponseInfo.ok(map);
    }

    @Override
    public ResponseInfo radPartDayPlan(MtlDPlanArrangeRep req, String choose) {
        if ("1".equals(choose)) {
            Integer num = prodDynamicHeadMapper.updatePartDayPlan(req);
            if (num <= 0) {
                return ResponseInfo.error("修改失败");
            }
            return ResponseInfo.ok();
        }
        prodDynamicHeadMapper.deletePartDayPlan(req);
        return ResponseInfo.ok("删除成功");
    }

    @Override
    public ResponseInfo getLine() {
        Map<Object, Object> map = new HashMap<>();
        List<Map<String, Object>> list = prodDynamicHeadMapper.getLine();
        map.put("list", list);
        return ResponseInfo.ok(map);
    }

    @Override
    public void downloadExcelPlan(PcProdArrangeReq req, HttpServletResponse response) throws IOException {
        String choose = req.getChoose();
        Map<String, String> map = new HashMap<>();
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + "x" + ".xlsx");
        BigDecimal total = new BigDecimal(0);
        String planType = null;
        String plan = null;
        AtomicInteger i = new AtomicInteger();
        String name = "";
        String name2 = "";
        switch (choose) {
            case "1":
                planType = "MTL";
                plan = "物料计划";
                name = "材料";
                name2 = "裁剪";
                break;
            case "2":
                planType = "DESIGN";
                plan = "板房计划";
                name = "板房";
                name2 = "裁剪";
                break;
            case "4":
                plan = "大底计划";
                planType = "SOLE";
                name = "针车";
                name2 = "大底";
                break;
            case "5":
                plan = "成型计划";
                planType = "LAST";
                name = "针车";
                name2 = "成型";
                break;
            case "3":
                plan = "针车计划";
                planType = "STITCH";
                break;

        }
        String endDate = prodDynamicHeadMapper.getEndDateMtl(req, planType);
        if ("3".equals(choose)) {
            List<PcStitchPlanRep> list = prodDynamicHeadMapper.arrangePlanListStitch(planType, req);
            stitchChange(list, i, total);
            InputStream inputStream = new ClassPathResource("templates/针车计划.xlsx").getInputStream();
            try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).excelType(ExcelTypeEnum.XLSX).withTemplate(inputStream).registerWriteHandler(new WorkbookWriteHandler() {
                @Override
                public void afterWorkbookCreate(WorkbookWriteHandlerContext context) {
                    Workbook workbook = context.getWriteWorkbookHolder().getWorkbook();
                    if (workbook instanceof SXSSFWorkbook) {
                        SXSSFWorkbook workbook1 = (SXSSFWorkbook) workbook;
                        workbook1.setCompressTempFiles(true);
                    }
                }
            }).build()) {
                WriteSheet writeSheet = EasyExcel.writerSheet().build();
                List<List<PcStitchPlanRep>> lists = ListUtils.partition(list, 100);
                for (List<PcStitchPlanRep> reps : lists) {
                    excelWriter.fill(reps, writeSheet);
                }
//                map.put("totalQty", total.toString());
                map.put("endDate", endDate);
                excelWriter.fill(map, writeSheet);
            }
        } else {
            List<MtlDPlanArrangeRep> list = prodDynamicHeadMapper.arrangePlanList(planType, req);
            InputStream inputStream = new ClassPathResource("templates/物料安排.xlsx").getInputStream();
            extracted(list, i, total);
            try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).excelType(ExcelTypeEnum.XLSX).withTemplate(inputStream).registerWriteHandler(new WorkbookWriteHandler() {
                @Override
                public void afterWorkbookCreate(WorkbookWriteHandlerContext context) {
                    Workbook workbook = context.getWriteWorkbookHolder().getWorkbook();
                    if (workbook instanceof SXSSFWorkbook) {
                        SXSSFWorkbook workbook1 = (SXSSFWorkbook) workbook;
                        workbook1.setCompressTempFiles(true);
                    }
                }
            }).build()) {
                WriteSheet writeSheet = EasyExcel.writerSheet().build();
                List<List<MtlDPlanArrangeRep>> lists = ListUtils.partition(list, 100);
                for (List<MtlDPlanArrangeRep> reps : lists) {
                    excelWriter.fill(reps, writeSheet);
                }
//                map.put("totalQty", total.toString());
                map.put("endDate", endDate);
                map.put("plan", plan);
                map.put("name", name);
                map.put("name2", name2);
                excelWriter.fill(map, writeSheet);
            }
        }
    }

    @Override
    public void downloadDayPlanList(HttpServletResponse response, PcDevPartDayPlanReq req) throws IOException {
        Map<String, Object> map = new HashMap<>();
        if (req.getEndTime() == null) {
            return;
        }
        List<MtlDPlanArrangeRep> list = prodDynamicHeadMapper.devPartDayPlanList(req);
        String line = req.getLine();
        list = list.stream().filter(x -> line.equals(x.getLine())).collect(Collectors.toList());
        BigDecimal total = new BigDecimal(0);
        int seqNo = 1;
        for (MtlDPlanArrangeRep rep : list) {
            rep.setSeqNo(seqNo++);
            if (rep.getPhotoPath() != null) {
                rep.setPhoto(new URL(rep.getPhotoPath()));
            }
            total = total.add(rep.getQty());
        }
        map.put("line", line);
        map.put("total", total);
        MtlDPlanArrangeRep rep = list.get(0);
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String s = format.format(rep.getCompleteDate());
        map.put("endTime", s);
        String fileName = "研发日计划_" + DateUtils.dateTimeNow();
        ExcelUtils.creatByTemplate(response, "研发日计划模板.xls", fileName, list, map);
    }

    @Override
    public ResponseInfo uploadPcOrderShoePlan(MultipartFile file) {
        List<PcOrderPlanExcel> list = excelInput(file);
        if (ObjectUtils.isEmpty(list)) {
            return ResponseInfo.error("请选择正确的文件!");
        }
        List<PcOrderPlanExcel> filteredList = list.stream()
                .filter(t -> !ObjectUtils.isEmpty(t.getLotNo()) && !ObjectUtils.isEmpty(t.getType()) && !ObjectUtils.isEmpty(t.getPlanDate()))
                .collect(Collectors.toList());
        for (PcOrderPlanExcel excel : filteredList) {
            Integer num = prodDynamicHeadMapper.insertIntoPcOrderPlan(excel, UserIdThread.get().getCompanyId());
            if (num <= 0) {
                throw new ServiceErrorException("订单未建档、样品订单未导入");
            }
        }
        return ResponseInfo.ok();
    }

    @Override
    @Transactional
    public ResponseInfo updatePcScheduleLot() {
        List<String> orderIds = prodDynamicHeadMapper.getUpdateLotByOrderHead();
        if (!ZStringUtils.isEmpty(orderIds)) prodDynamicHeadMapper.insertIntoPcOrderLot(orderIds, UserIdThread.get());
        return ResponseInfo.ok("更新成功");
    }

    @Override
    public void downloadPcOrderSch(HttpServletResponse response) throws IOException {
        Map<String, String> map = new HashMap<>();
        List<Map<String, Object>> list = prodDynamicHeadMapper.getPcOrderSch();
        BigDecimal total = new BigDecimal(0);
        if (!ZStringUtils.isEmpty(list)) {
            for (Map<String, Object> stringMap : list) {
                total = total.add((BigDecimal) stringMap.get("orderQty"));
            }
        }
        String scheduleNo = prodDynamicHeadMapper.getScheduleNo();
        map.put("scheduleNo", scheduleNo);
        map.put("total", total.toString());
        ExcelUtils.creatByTemplate(response, "进度表模板.xls", "jdb"+DateUtils.dateTimeNow(), list, map);
    }

    @Override
    public ResponseInfo getLine1() {
        List<Map<String,Object>> list = prodDynamicHeadMapper.getLine1(UserIdThread.get().getCompanyId());
        return ResponseInfo.ok(list);
    }

    @Override
    public ResponseInfo updatePcLine1(Map<String, Object> map) {
        prodDynamicHeadMapper.updatePcLine1(map);
        return ResponseInfo.ok();
    }

    public List<PcOrderPlanExcel> excelInput(MultipartFile excelFile) {
        String excelFileName = excelFile.getOriginalFilename();
        int excelVersion = ExcelPoiUtils.getExcelVersion(excelFileName);
        Workbook workbook = null;
        List<PcOrderPlanExcel> list = null;

        // 2003版本xls
        if (excelVersion == 1) {
            try {
                log.info("导入文件名:{},文件版本:2003", excelFileName);
                workbook = new HSSFWorkbook(excelFile.getInputStream());
                list = readExcelValue(workbook);
                return list;
            } catch (Exception e) {
                log.error("文件导入失败!");
                e.printStackTrace();
            }
        }
        // 2007版本xlsx
        if (excelVersion == 2) {
            try {
                log.info("导入文件名:{},文件版本:2007", excelFileName);
                workbook = new XSSFWorkbook(excelFile.getInputStream());
                list = readExcelValue(workbook);
                return list;
            } catch (Exception e) {
                log.error("文件导入失败!");
                e.printStackTrace();
            }
        }
        return null;
    }

    private List<PcOrderPlanExcel> readExcelValue(Workbook workbook) throws ParseException {
        int totalRows = 0;
        int totalCells = 0;
        Sheet sheet = workbook.getSheetAt(1);
        totalRows = sheet.getPhysicalNumberOfRows();
        if (totalRows >= 1 && sheet.getRow(0) != null) {
            totalCells = sheet.getRow(0).getPhysicalNumberOfCells();
        }
        List<PcOrderPlanExcel> list = new ArrayList<>();
        for (int rowNum = 2; rowNum < totalRows; rowNum++) {
            Row row = sheet.getRow(rowNum);
            if (row == null) {
                continue;
            }
            PcOrderPlanExcel vo = new PcOrderPlanExcel();
            for (int colNum = 0; colNum < totalCells; colNum++) {
                Cell cell = row.getCell(colNum);
                if (null != cell) {
                    switch (cell.getCellType()) {
                        case NUMERIC:
                            if (colNum == 4) {
                                double value = cell.getNumericCellValue();
                                long time = (long) ((value - 25569) * 86400 * 1000);
                                Date date = new Date(time);
                                vo.setPlanDate(date);
                            }
                            break;
                        case STRING:
                            if (colNum == 3) {
                                vo.setLotNo(cell.getStringCellValue());
                            }
                            if (colNum == 5) {
                                vo.setType(cell.getStringCellValue());
                            }
                            break;
                        case BOOLEAN:
                            break;
                        case FORMULA:
                            break;
                        case BLANK:
                            break;
                        default:
                    }
                }
            }
            list.add(vo);
        }
        return list;
    }

    private static void stitchChange(List<PcStitchPlanRep> list, AtomicInteger i, BigDecimal total) {
        list.forEach(
                x -> {
                    x.setSeqNo(i.incrementAndGet());
                    total.add(x.getQty());
                    try {
                        if (x.getPhotoPath() != null) {
                            x.setPhoto(new URL(x.getPhotoPath()));
                        }
                    } catch (MalformedURLException e) {
                        throw new RuntimeException(e);
                    }
                }
        );
    }

    private static void extracted(List<MtlDPlanArrangeRep> list, AtomicInteger i, BigDecimal total) {
        list.forEach(x -> {
            x.setSeqNo(i.incrementAndGet());
            total.add(x.getQty());
            try {
                if (x.getPhotoPath() != null) {
                    x.setPhoto(new URL(x.getPhotoPath()));
                }
            } catch (MalformedURLException e) {
                throw new RuntimeException(e);
            }
        });
    }
}
